package com.ruoyi.system.service;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * 腾讯云COS文件上传服务
 * 
 * @author ruoyi
 */
@Service
public class TencentCosService {
    
    private static final Logger logger = LoggerFactory.getLogger(TencentCosService.class);
    
    @Value("${cos.access_key}")
    private String accessKey;
    
    @Value("${cos.secret_key}")
    private String secretKey;
    
    @Value("${cos.region_name}")
    private String regionName;
    
    @Value("${cos.bucket_name}")
    private String bucketName;
    
    @Value("${cos.key_name:images}")
    private String keyName;
    
    /**
     * 初始化COS客户端
     * 
     * @return COSClient实例
     */
    private COSClient initCOSClient() {
        logger.info("初始化COS客户端，配置信息: accessKey={}, regionName={}, bucketName={}, keyName={}", 
                    accessKey != null ? accessKey.substring(0, Math.min(10, accessKey.length())) + "..." : "null", 
                    regionName, bucketName, keyName);
        // 1 初始化用户身份信息(accessKey, secretKey)
        COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey);
        
        // 2 设置bucket的区域
        ClientConfig clientConfig = new ClientConfig(new Region(regionName));
        
        // 3 生成cos客户端
        return new COSClient(cred, clientConfig);
    }
    
    /**
     * 上传文件到腾讯云COS
     * 
     * @param file 要上传的文件
     * @return 文件的完整访问URL
     * @throws IOException 上传异常
     */
    public String uploadFile(MultipartFile file) throws IOException {
        logger.info("开始上传文件到腾讯云COS，文件名: {}, 文件大小: {}", file.getOriginalFilename(), file.getSize());
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }
        
        COSClient cosClient = null;
        
        try {
            // 获取文件类型
            String originalFilename = file.getOriginalFilename();
            String fileExtension = "";
            if (originalFilename != null && originalFilename.contains(".")) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            }
            
            // 生成随机文件名，避免重复
            String randomFileName = UUID.randomUUID().toString().replace("-", "") + fileExtension;
            
            // 构建COS中的文件路径
            String cosKey = keyName + "/" + randomFileName;
            
            // 初始化COS客户端
            cosClient = initCOSClient();
            
            // 创建临时文件
            File tempFile = File.createTempFile("upload_", fileExtension);
            file.transferTo(tempFile);
            
            try {
                // 创建上传请求
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, cosKey, tempFile);
                
                // 执行上传
                PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
                
                // 构建访问URL
                String fileUrl = String.format("https://%s.cos.%s.myqcloud.com/%s", bucketName, regionName, cosKey);
                
                logger.info("文件上传成功，URL: {}", fileUrl);
                return fileUrl;
                
            } finally {
                // 删除临时文件
                if (tempFile.exists()) {
                    tempFile.delete();
                }
            }
            
        } catch (CosServiceException e) {
            logger.error("腾讯云COS服务异常: {}", e.getMessage(), e);
            throw new IOException("腾讯云COS服务异常: " + e.getMessage(), e);
        } catch (CosClientException e) {
            logger.error("腾讯云COS客户端异常: {}", e.getMessage(), e);
            throw new IOException("腾讯云COS客户端异常: " + e.getMessage(), e);
        } catch (Exception e) {
            logger.error("文件上传异常: {}", e.getMessage(), e);
            throw new IOException("文件上传异常: " + e.getMessage(), e);
        } finally {
            // 关闭客户端连接
            if (cosClient != null) {
                cosClient.shutdown();
            }
        }
    }
    
    /**
     * 删除COS中的文件
     * 
     * @param fileUrl 文件URL
     * @return 删除结果
     */
    public boolean deleteFile(String fileUrl) {
        COSClient cosClient = null;
        
        try {
            // 从URL中提取文件key
            String cosKey = extractKeyFromUrl(fileUrl);
            if (cosKey == null) {
                logger.warn("无法从URL中提取文件key: {}", fileUrl);
                return false;
            }
            
            cosClient = initCOSClient();
            cosClient.deleteObject(bucketName, cosKey);
            
            logger.info("文件删除成功: {}", fileUrl);
            return true;
            
        } catch (Exception e) {
            logger.error("删除文件失败: {}, 错误: {}", fileUrl, e.getMessage(), e);
            return false;
        } finally {
            if (cosClient != null) {
                cosClient.shutdown();
            }
        }
    }
    
    /**
     * 从URL中提取COS文件key
     * 
     * @param fileUrl 文件URL
     * @return 文件key
     */
    private String extractKeyFromUrl(String fileUrl) {
        try {
            // 腾讯云COS URL格式: https://bucket-name.cos.region.myqcloud.com/key
            String pattern = String.format("https://%s\\.cos\\.%s\\.myqcloud\\.com/", bucketName, regionName);
            if (fileUrl.startsWith(pattern.replace("\\", ""))) {
                return fileUrl.substring(pattern.replace("\\", "").length());
            }
            return null;
        } catch (Exception e) {
            logger.error("提取文件key失败: {}", e.getMessage());
            return null;
        }
    }
}